package com.easyidea.its.util;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.TimeZone;

public final class DateUtil {
	private static DateUtil instance = null;

	public static DateUtil getInstance() {
		if (instance == null) {
			instance = new DateUtil();
		}
		return instance;
	}

	private DateUtil() {
	}

	public static Date now() {
		return new Date();
	}

	public static Timestamp timestampNow() {
		return new Timestamp(new Date().getTime());
	}

	/**
	 * convert string to date, with default pattern,throws ParseException
	 * 
	 * @param strDate
	 *            the str date
	 * @return date
	 */
	public static Date strToDate(String strDate) {
		return strToDate(strDate, ItsConstants.FORMATE_STYLE_DATA_SHORT);
	}

	/**
	 * convert string to date ,with custom pattern,throws
	 * IllegalArgumentException
	 * 
	 * @param strDate
	 *            str
	 * @param format
	 *            format style such as yyyy-MM-dd
	 * @return the date.
	 */
	public static Date strToDate(String strDate, String format) {
		if (strDate == null) {
			return null;
		}

		Date result = null;
		try {
			SimpleDateFormat formater = new SimpleDateFormat(format);
			result = formater.parse(strDate);
		} catch (ParseException e) {
			throw new RuntimeException("String To Date Convert Error", e);
		}
		return result;
	}

	/**
	 * Date to String format as CEMConstants.FORMATE_STYLE_DATA("yyyy-MM-dd").
	 * 
	 * @param date
	 *            date.
	 * @return the string value format as
	 *         CEMConstants.FORMATE_STYLE_DATA("yyyy-MM-dd").
	 */
	public static String dateToShortStr(Date date) {
		return dateToStr(date, ItsConstants.FORMATE_STYLE_DATA_SHORT);
	}

	public static String dateToLongStr(Date date) {
		return dateToStr(date, ItsConstants.FORMATE_STYLE_DATA_LONG);
	}

	public static String dateToLongStr(Date date, Integer hour, Integer minute) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(Calendar.HOUR_OF_DAY, hour == null ? 0 : hour);
		cal.set(Calendar.MINUTE, minute == null ? 0 : minute);
		cal.set(Calendar.SECOND, 0);

		return dateToLongStr(cal.getTime());
	}

	/**
	 * Date to String accroding to the format.
	 * 
	 * @param date
	 *            date
	 * @param format
	 *            format
	 * @return the string format of the data value.
	 */
	public static String dateToStr(Date date, String format) {
		SimpleDateFormat formater = new SimpleDateFormat(format);
		return formater.format(date);
	}

	/**
	 * 获得给定时间的00:00:00
	 * 
	 * @param date
	 * @return
	 */

	public static Date getStartTime(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(dealwithDateNull(date));

		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		Date startTime = calendar.getTime();
		// startTime.setHours(0);
		// startTime.setMinutes(0);
		// startTime.setSeconds(0);
		return startTime;
	}

	/**
	 * 获得当天的开始时间00:00:00
	 * 
	 * @return
	 */
	public static Date getTodayStart() {
		return getStartTime(now());
	}

	/**
	 * 获得当天的结束时间23:59:59
	 * 
	 * @return
	 */
	public static Date getTodayEnd() {
		return getEndTime(now());
	}

	/**
	 * 获得给定时间的23:59:59
	 * 
	 * @param date
	 * @return
	 */
	public static Date getEndTime(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(dealwithDateNull(date));

		calendar.set(Calendar.HOUR_OF_DAY, 23);
		calendar.set(Calendar.MINUTE, 59);
		calendar.set(Calendar.SECOND, 59);
		Date startTime = calendar.getTime();
		// startTime.setHours(23);
		// startTime.setMinutes(59);
		// startTime.setSeconds(59);
		return startTime;
	}

	/**
	 * Deal with the date -- if the date is null then return the current time
	 * otherwise return itself.
	 * 
	 * @param date
	 *            date
	 * @return date
	 */
	public static Date dealwithDateNull(Date date) {
		if (date == null) {
			return new Date();
		}
		return date;
	}

	// add by alex.su@2008-6-4
	/**
	 * GMT+8 timzone offset value.
	 */
	public static final String CST_TIMEZONE_OFFSET = "-480";

	/**
	 * Convert the date to GMT.
	 * 
	 * @param date
	 *            date.
	 * @return GMT Date.
	 */
	public static Date toGMTDate(Date date, String timeZoneDigital) {
		if (date == null) {
			return null;
		}

		Calendar cal = Calendar.getInstance(getTimeZone(timeZoneDigital));
		cal.setTime(date);

		cal.add(Calendar.HOUR_OF_DAY, getTimeOffSet(timeZoneDigital));
		// add at 20071015 by Jeecy for the timezone maybe infact minute.
		cal.add(Calendar.MINUTE, getMinuteOffSet(timeZoneDigital));
		return cal.getTime();
	}

	/**
	 * Convert the date to GMT.
	 * 
	 * @param strDate
	 *            strDate.
	 * @return GMT Date.
	 */
	public static Date toGMTDate(String strDate, String timeZoneDigital) {
		Date date = strToDate(strDate);
		Calendar cal = Calendar.getInstance(getTimeZone(timeZoneDigital));
		cal.setTime(date);

		cal.add(Calendar.HOUR_OF_DAY, getTimeOffSet(timeZoneDigital));
		// add at 20071015 by Jeecy for the timezone maybe infact minute.
		cal.add(Calendar.MINUTE, getMinuteOffSet(timeZoneDigital));
		return cal.getTime();
	}

	/**
	 * Convert date to the special timezone date.<br>
	 * If timeZoneDigital==null, default convert to GMT+8(CST).
	 * 
	 * @param date
	 *            date
	 * @param timeZoneDigital
	 *            timeZoneDigital
	 * @return the special timezone date.
	 */
	public static Date toLocalDate(Date date, String timeZoneDigital) {
		Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
		cal.setTime(date);
		cal.add(Calendar.HOUR_OF_DAY, -getTimeOffSet(timeZoneDigital));
		// add at 20071015 by Jeecy for the timezone maybe infact minute.
		cal.add(Calendar.MINUTE, -getMinuteOffSet(timeZoneDigital));
		return cal.getTime();
	}

	/**
	 * Get the timezone according to the timeZone_digital. <br>
	 * If the timeZoneDigital==null, default return GMT+8(CST).
	 * 
	 * @param timeZoneDigital
	 * @return
	 */
	public static TimeZone getTimeZone(String timeZoneDigital) {
		String gmt = "";
		if (timeZoneDigital != null) {
			int length = timeZoneDigital.length();
			String f = "";
			if (length == 1) {
				gmt = "GMT";
			} else if (timeZoneDigital.startsWith("-")) {
				f = timeZoneDigital.substring(1, length);
				gmt = "GMT+" + Integer.parseInt(f) / 60;
			} else {
				gmt = "GMT-" + Integer.parseInt(timeZoneDigital) / 60;
			}

		} else {
			return TimeZone.getTimeZone("GMT+8");
		}
		return TimeZone.getTimeZone(gmt);
	}

	private static int getTimeOffSet(String timeZoneDigital) {
		String localTimeZone = CST_TIMEZONE_OFFSET;
		if (timeZoneDigital != null && timeZoneDigital.trim().length() > 0) {
			localTimeZone = timeZoneDigital;
		}
		return Integer.parseInt(localTimeZone) / 60;
	}

	private static int getMinuteOffSet(String timeZoneDigital) {
		String localTimeZone = CST_TIMEZONE_OFFSET;
		if (timeZoneDigital != null && timeZoneDigital.trim().length() > 0) {
			localTimeZone = timeZoneDigital;
		}
		return (Integer.parseInt(localTimeZone) % 60);
	}

	public static Date getDateByCombined(int year, String month) {
		Calendar cca1 = Calendar.getInstance();
		cca1.set(year, getSingDay(month) - 1, 1);
		return cca1.getTime();
	}

	public static Date getFirstDayOfMonth(int year, String month) {
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.YEAR, year);// 年
		calendar.set(Calendar.MONTH, getSingDay(month) - 1);
		calendar.set(Calendar.DATE, 1);
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		return calendar.getTime();
	}

	public static Date getLastDayOfMonth(int year, String month) {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.YEAR, year);// 年
		cal.set(Calendar.MONTH, getSingDay(month) - 1);// 月，因为Calendar里的月是从0开始，
		// 所以要减1
		cal.set(Calendar.DATE, 1);// 日，设为一号
		cal.add(Calendar.MONTH, 1);// 月份加一，得到下个月的一号
		cal.add(Calendar.DATE, -1);// 下一个月减一为本月最后一天
		cal.set(Calendar.HOUR_OF_DAY, 23);
		cal.set(Calendar.MINUTE, 59);
		cal.set(Calendar.SECOND, 59);
		return cal.getTime();
	}

	private static int getSingDay(String dateStr) {
		String subStr = dateStr.substring(0);
		if (subStr.equalsIgnoreCase("0")) {
			return Integer.parseInt(dateStr.substring(1, 1));
		} else {
			return Integer.parseInt(dateStr);
		}
	}

	public static int getYear(Date date) {
		SimpleDateFormat yearFm = new SimpleDateFormat("yyyy");
		return Integer.parseInt(yearFm.format(date));
	}

	public static String getMonth(Date date) {
		SimpleDateFormat monthFm = new SimpleDateFormat("MM");
		return monthFm.format(date);
	}

	public static int getDay(Date date) {
		SimpleDateFormat dayFm = new SimpleDateFormat("dd");
		return Integer.parseInt(dayFm.format(date));
	}

	public static int getHour(Date date) {
		SimpleDateFormat dayFm = new SimpleDateFormat("HH");
		return Integer.parseInt(dayFm.format(date));
	}

	public static Collection<Date> buildDayColByTimeRange(Date startDate, Date endDate) {
		Collection<Date> dayCol = new ArrayList<Date>();
		if (null != startDate && null != endDate) {
			startDate = getStartTime(startDate);
			endDate = getStartTime(endDate);

			Date nextDate = new Date(startDate.getTime() + 24 * 3600 * 1000L);
			while (nextDate.getTime() <= endDate.getTime()) {
				if (nextDate.getTime() <= endDate.getTime()) {
					dayCol.add(nextDate);
				}
				nextDate = new Date(nextDate.getTime() + 24 * 3600 * 1000L);
			}
		}

		return dayCol;
	}

	public static Date getDateBerforByWeek(Date date, int weekNum) {
		int dayNum = weekNum * 7 - 1;
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.DATE, -dayNum);
		Date d = cal.getTime();
		return d;
	}

	/**
	 * 返回date所在周(包括date周)前periods周的起始时间
	 * 
	 * @param date
	 * @param periods
	 * @return
	 */
	public static Date getStartDateForWeekSearch(Date date, int periods) {
		SimpleDateFormat yearFm = new SimpleDateFormat("yyyy");
		SimpleDateFormat weekFm = new SimpleDateFormat("w");
		// int currYear = Integer.parseInt(yearFm.format(date));
		// int currWeek = Integer.parseInt(weekFm.format(date));

		Calendar c = Calendar.getInstance();
		c.set(Calendar.DAY_OF_WEEK, ItsConstants.FIRST_DAY_IN_WEEK);
		c.setMinimalDaysInFirstWeek(7);
		c.setTime(date);
		c.add(Calendar.WEEK_OF_YEAR, -periods + 1);
		c.setFirstDayOfWeek(ItsConstants.FIRST_DAY_IN_WEEK);
		c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek());

		return getStartTime(c.getTime());
	}

	/**
	 * 返回date所在周的结束时间
	 * 
	 * @param date
	 * @return
	 */
	public static Date getEndDateForWeekSearch(Date date) {
		Calendar c = Calendar.getInstance();
		c.setFirstDayOfWeek(ItsConstants.FIRST_DAY_IN_WEEK);
		c.setTime(date);
		c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek() + 6);
		return getEndTime(c.getTime());
	}

	public static Date addDate(Date date, int day) {
		Calendar fromCal = Calendar.getInstance();
		fromCal.setTime(date);
		fromCal.add(Calendar.DATE, day);
		return fromCal.getTime();

	}

	public static Date getYestoday() {
		Calendar c = Calendar.getInstance();
		c.add(Calendar.DAY_OF_MONTH, -1);
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String mDateTime = formatter.format(c.getTime());
		String strStart = mDateTime.substring(0, 16);//
		return strToDate(strStart);
	}

	public static long getdate(Date date1, Date date2) {
		long day = (date1.getTime() - date2.getTime()) / (24 * 60 * 60 * 1000) > 0 ? (date1.getTime() - date2.getTime()) / (24 * 60 * 60 * 1000)
				: (date2.getTime() - date1.getTime()) / (24 * 60 * 60 * 1000);
		return day;
	}

}
